package com.simple.orm.agreement.process.impl;

import com.simple.orm.agreement.annotation.AgreementProcess;
import com.simple.orm.agreement.manager.impl.ProtocolManager;
import com.simple.orm.agreement.process.ReadProcess;

import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class AutoReadProcess {

    public static <T> T readData(byte[] data, ReadProcess.DescribeEvent describeEvent, boolean isPackage) throws IOException {
        int flag = isPackage ? (data[4] << 24) + (data[1 + 4] << 16) + (data[2 + 4] << 8) + (data[3 + 4]) : (data[0] << 24) + (data[1] << 16) + (data[2] << 8) + data[3];
        Class<?> aClass = ProtocolManager.getInstance().lookup(flag);
        if (aClass == null) throw new IllegalArgumentException(String.format("未知的协议：%s", flag));
        AgreementProcess agreementProcess = aClass.getDeclaredAnnotation(AgreementProcess.class);
        Class<? extends ReadProcess> clazz = DefaultReadProcess.class;
        if (agreementProcess != null) clazz = agreementProcess.readProcess();
        ReadProcess readProcess = instance(clazz);
        readProcess.setDescribeEvent(describeEvent);
        return (T) readProcess.readFrom(data, isPackage);
    }

    /**
     * 实例化对象
     *
     * @param tClass 被实例化的对象的类对象
     * @return 实例化的对象
     */
    protected static <T> T instance(Class<T> tClass) {
        Constructor<T>[] constructors = (Constructor<T>[]) tClass.getDeclaredConstructors();
        for (Constructor<T> constructor : constructors) {
            if (constructor.getParameterCount() > 0) continue;
            boolean accessible = constructor.isAccessible();
            try {
                return constructor.newInstance();
            } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
                throw new RuntimeException(e);
            } finally {
                constructor.setAccessible(accessible);
            }
        }
        throw new IllegalArgumentException("找不到无参构造方法，无法实例化目标");
    }
}
